package config

import (
	"fmt"
	"log"
	"os"
	"strconv"
	"time"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

type Config struct {
	AppName        string
	Env            string
	Debug          bool
	Port           int
	DBHost         string
	DBPort         int
	DBDatabase     string
	DBUsername     string
	DBPassword     string
	JWTSecret      string
	JWTExpireHours int
	WechatAppID    string
	WechatSecret   string
	UploadPath     string
	MaxUploadSize  int64
}

var DB *gorm.DB

func Load() *Config {
	return &Config{
		AppName:        getEnv("APP_NAME", "围棋管理系统"),
		Env:            getEnv("APP_ENV", "development"),
		Debug:          getEnvBool("APP_DEBUG", true),
		Port:           getEnvInt("APP_PORT", 8088),
		DBHost:         getEnv("DB_HOST", "127.0.0.1"),
		DBPort:         getEnvInt("DB_PORT", 3306),
		DBDatabase:     getEnv("DB_DATABASE", "go_system"),
		DBUsername:     getEnv("DB_USERNAME", "go_system"),
		DBPassword:     getEnv("DB_PASSWORD", "123456"),
		JWTSecret:      getEnv("JWT_SECRET", "your_secret_key_here"),
		JWTExpireHours: getEnvInt("JWT_EXPIRE_HOURS", 72),
		WechatAppID:    getEnv("WECHAT_APPID", ""),
		WechatSecret:   getEnv("WECHAT_SECRET", ""),
		UploadPath:     getEnv("UPLOAD_PATH", "./uploads"),
		MaxUploadSize:  int64(getEnvInt("MAX_UPLOAD_SIZE", 10485760)),
	}
}

func InitDB(cfg *Config) error {
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
		cfg.DBUsername,
		cfg.DBPassword,
		cfg.DBHost,
		cfg.DBPort,
		cfg.DBDatabase,
	)

	logLevel := logger.Silent
	if cfg.Debug {
		logLevel = logger.Info
	}

	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: logger.Default.LogMode(logLevel),
		NowFunc: func() time.Time {
			return time.Now().Local()
		},
	})

	if err != nil {
		return err
	}

	sqlDB, err := db.DB()
	if err != nil {
		return err
	}

	sqlDB.SetMaxIdleConns(10)
	sqlDB.SetMaxOpenConns(100)
	sqlDB.SetConnMaxLifetime(time.Hour)

	DB = db
	log.Println("✅ Database connected successfully")
	return nil
}

func GetDB() *gorm.DB {
	return DB
}

func getEnv(key, defaultValue string) string {
	if value := os.Getenv(key); value != "" {
		return value
	}
	return defaultValue
}

func getEnvInt(key string, defaultValue int) int {
	if value := os.Getenv(key); value != "" {
		if intValue, err := strconv.Atoi(value); err == nil {
			return intValue
		}
	}
	return defaultValue
}

func getEnvBool(key string, defaultValue bool) bool {
	if value := os.Getenv(key); value != "" {
		if boolValue, err := strconv.ParseBool(value); err == nil {
			return boolValue
		}
	}
	return defaultValue
}
